from neo4j import GraphDatabase, AsyncGraphDatabase
import asyncio

# 全局单例 driver
_driver_sync = None
_driver_async = None


def is_async_context() -> bool:
    """判断当前是否处于异步上下文"""
    try:
        asyncio.get_running_loop()
        return True
    except RuntimeError:
        return False


def linkNeo4j(
    db_name: str = "neo4j",
    user: str = "neo4j",
    password: str = "test1234",
    uri: str = "bolt://localhost:7687",
):
    """
    根据当前上下文返回同步或异步 Neo4j 会话对象
    成功返回 (session, driver)，失败直接抛异常
    """
    if is_async_context():
        return _neo4j_async(db_name, user, password, uri)
    else:
        return _neo4j_sync(db_name, user, password, uri)


def _neo4j_sync(db_name, user, password, uri):
    """同步连接 Neo4j，driver 全局复用，失败直接抛异常"""
    global _driver_sync
    try:
        if _driver_sync is None:
            _driver_sync = GraphDatabase.driver(uri, auth=(user, password))
        session = _driver_sync.session(database=db_name)
        return session, _driver_sync
    except Exception as e:
        raise ConnectionError(f"❌ 连接 Neo4j 数据库「{db_name}」失败: {e}") from e


async def _neo4j_async(db_name, user, password, uri):
    """异步连接 Neo4j，driver 全局复用，失败直接抛异常"""
    global _driver_async
    try:
        if _driver_async is None:
            _driver_async = AsyncGraphDatabase.driver(
                uri, auth=(user, password))
        session = _driver_async.session(database=db_name)
        return session, _driver_async
    except Exception as e:
        raise ConnectionError(f"❌ 异步连接 Neo4j 数据库「{db_name}」失败: {e}") from e
